home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / games / sprocketinvaders / source / graphics.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  11.0 KB  |  408 lines

  1. //•    ------------------------------------------------------------------------------------------    •
  2. //•
  3. //•    Copyright © 1996-1999 Apple Computer, Inc., All Rights Reserved
  4. //•
  5. //•
  6. //•        You may incorporate this sample code into your applications without
  7. //•        restriction, though the sample code has been provided "AS IS" and the
  8. //•        responsibility for its operation is 100% yours.  However, what you are
  9. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  10. //•        after having made changes. If you're going to re-distribute the source,
  11. //•        we require that you make it clear in the source that the code was
  12. //•        descended from Apple Sample Code, but that you've made changes.
  13. //•
  14. //•        Authors:
  15. //•            Chris De Salvo
  16. //•
  17. //•    ------------------------------------------------------------------------------------------    •
  18.  
  19. //•    ------------------------------    Includes
  20.  
  21. #include <Types.h>
  22. #include <Resources.h>
  23.  
  24. #include <string.h>
  25.  
  26. #include "DrawSprocket.h"
  27. #include "ErrorHandler.h"
  28. #include "Graphics.h"
  29. #include "MemoryHandler.h"
  30. #include "SIResources.h"
  31. #include "Sprite.h"
  32.  
  33. //•    ------------------------------    Private Definitions
  34.  
  35. #define kFirstIconColor                1
  36. #define kLastIconColor                33
  37.  
  38. #define kFirstBGColor                34
  39. #define kLastBGColor                183
  40.  
  41. #define kFirstSpriteColor            184
  42. #define kLastSpriteColor            254
  43.  
  44. //•    ------------------------------    Private Types
  45. //•    ------------------------------    Private Variables
  46.  
  47. static DSpAltBufferReference        gUnderlay;
  48. static CTabHandle                    gGameCLUT;
  49.  
  50. //•    ------------------------------    Private Functions
  51.  
  52. static void GraphicsUpdateScreenPalette(UInt16 inFirstColor, UInt16 inLastColor);
  53. static void GraphicsCreateUnderlay(void);
  54. static void GraphicsSelectContext(SInt16 modifiers);
  55. static void GraphicsInitAttributes(DSpContextAttributes *inAttributes);
  56.  
  57. //•    ------------------------------    Public Variables
  58.  
  59. DSpContextReference        gDisplayContext;
  60. DSpContextAttributes    gDisplayAttributes;
  61. GDHandle                gGameGDH;
  62.  
  63. const RGBColor    rgbBlack    = { 0x0000, 0x0000, 0x0000 };
  64. const RGBColor    rgbWhite    = { 0xFFFF, 0xFFFF, 0xFFFF };
  65. const RGBColor    rgbRed        = { 0xFFFF, 0x0000, 0x0000 };
  66. const RGBColor    rgbBlue        = { 0x0000, 0x0000, 0xFFFF };
  67. const RGBColor    rgbYellow    = { 0xFFFF, 0xFFFF, 0x0000 };
  68. const RGBColor    rgbGreen    = { 0x0000, 0xFFFF, 0x0000 };
  69.  
  70. #pragma mark —————  Startup/Shutdown  —————
  71.  
  72. //•    --------------------    GraphicsInit
  73.  
  74. void
  75. GraphicsInit(SInt16 modifiers)
  76. {
  77. CGrafPtr    backBuffer;
  78. OSErr        theErr;
  79. Rect        r = { 40, 40, 100, 100 };
  80.  
  81.     theErr = DSpStartup();
  82.     if (theErr)
  83.         FatalError("GraphicsInit: DSpStartup() failed!!!!");
  84.  
  85.     //•    CLUT 8 is the standard 8-bit color system color table and is
  86.     //•    always present
  87.     gGameCLUT = GetCTable(8);
  88.     DetachResource((Handle) gGameCLUT);
  89.     
  90.     //•    Define and create our drawing context
  91.     GraphicsSelectContext(modifiers);
  92.  
  93.     //•    Add our various colors to the color table
  94.     GraphicsMergeCLUT(128, kFirstIconColor, kLastIconColor);
  95.     GraphicsMergeCLUT(kPICTGasCloud, kFirstBGColor, kLastBGColor);
  96.     GraphicsMergeCLUT(kCLUTSprites, kFirstSpriteColor, kLastSpriteColor);
  97.  
  98.     //•    Create our underlay and load a picture into it
  99.     GraphicsCreateUnderlay();
  100.     GraphicsLoadBackground(kPICTGasCloud);
  101.  
  102.     //•    Swap the buffers once to get the underlay image on the screen
  103.     DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &backBuffer);
  104.     DSpContext_InvalBackBufferRect(gDisplayContext, &backBuffer->portRect);
  105.     GraphicsUpdateScreen();
  106.  
  107.     //•    Fade up from black and then put the context in the paused state
  108.     //•    so that the user has access to the menu bar.
  109.     DSpContext_FadeGammaIn(nil, nil);
  110.     GraphicsPaused();
  111. }
  112.  
  113. //•    --------------------    GraphicsReset
  114.  
  115. void
  116. GraphicsReset(void)
  117. {
  118.     DSpContext_FadeGammaOut(nil, nil);
  119.     GraphicsInactive();
  120.     DSpContext_FadeGammaIn(nil, nil);
  121.  
  122.     DSpContext_Release(gDisplayContext);
  123.     DSpShutdown();
  124. }
  125.  
  126. #pragma mark —————  Context Management  —————
  127.  
  128. //•    --------------------    GraphicsSelectContext
  129.  
  130. static void
  131. GraphicsSelectContext(SInt16 modifiers)
  132. {
  133. OSStatus        theError;
  134. DisplayIDType    displayID;
  135.     
  136.     //•    Initialize our context description
  137.     GraphicsInitAttributes(&gDisplayAttributes);
  138.  
  139.     //•    Tell DrawSprocket the exact needs we have for our game
  140.     gDisplayAttributes.displayWidth            = 640;
  141.     gDisplayAttributes.displayHeight        = 480;
  142.     gDisplayAttributes.colorNeeds            = kDSpColorNeeds_Require;
  143.     gDisplayAttributes.backBufferDepthMask    = kDSpDepthMask_8;
  144.     gDisplayAttributes.displayDepthMask        = kDSpDepthMask_8;
  145.     gDisplayAttributes.backBufferBestDepth    = 8;
  146.     gDisplayAttributes.displayBestDepth        = 8;
  147.     gDisplayAttributes.pageCount            = 2;
  148.     gDisplayAttributes.colorTable            = gGameCLUT;
  149.  
  150.     //•    Find the best context for these attributes
  151.     //•    This call will check to see if multiple monitors can handle the request
  152.     //•    If there is more than one valid device it will put up the selection interface
  153.     theError = DSpUserSelectContext(&gDisplayAttributes, 0L, nil, &gDisplayContext);
  154.  
  155.     if (theError)
  156.         FatalError("A suitable display context could not be found.");
  157.  
  158.     if (modifiers & optionKey)
  159.         gDisplayAttributes.contextOptions |= kDSpContextOption_DontSyncVBL;
  160.  
  161.     //•    Page flipping only works on 7500/7600/8500/8600 machines and only when
  162.     //•    there is >= 4 MB of VRAM.  There are very few of these machines in
  163.     //•    existance so turning on this option is not recommended.
  164.     //•    gDisplayAttributes.contextOptions |= kDSpContextOption_PageFlip;
  165.  
  166.     //•    Set the blanking color to black
  167.     DSpSetBlankingColor(&rgbBlack);
  168.  
  169.     //•    Find the DisplayID for this draw context and then find the GDevice
  170.     //•    that goes along with it.  We need this because if we need to perform
  171.     //•    QuickDraw operations in a context that isn't on the main monitor then
  172.     //•    we need to have the proper GDevice set or QuickDraw loses its mind.
  173.     theError =  DSpContext_GetDisplayID(gDisplayContext, &displayID);
  174.     if (theError)
  175.         FatalError("DSpContext_GetDisplayID() had an error.");
  176.  
  177.     theError = DMGetGDeviceByDisplayID(displayID, &gGameGDH, false);
  178.     if (theError)
  179.         FatalError("DMGetGDeviceByDisplayID() had an error.");
  180.  
  181.     //•    Reserve the draw context so that we get the attributes we want
  182.     theError = DSpContext_Reserve(gDisplayContext, &gDisplayAttributes);
  183.     if (theError)
  184.         FatalError("Could not reserve display context.");
  185.  
  186.     //•    Fade the screen to black and make our context active
  187.     DSpContext_FadeGammaOut(nil, nil);
  188.     GraphicsActive();
  189. }
  190.  
  191. //•    --------------------    GraphicsInitAttributes
  192.  
  193. static void
  194. GraphicsInitAttributes(DSpContextAttributes *inAttributes)
  195. {
  196.     if (! inAttributes)
  197.         FatalError("Nil context passed to MyInitAttributes().");
  198.  
  199.     memset(inAttributes, 0, sizeof (DSpContextAttributes));
  200. }
  201.  
  202. //•    --------------------    GraphicaCreateUnderlay
  203.  
  204. static void
  205. GraphicsCreateUnderlay(void)
  206. {
  207. OSStatus    theError;
  208.  
  209.     //•    Create a new alt buffer which mimics the onscreen display
  210.     theError = DSpAltBuffer_New(gDisplayContext, true, 0L, &gUnderlay);
  211.     if (theError)
  212.         FatalError("Could not create underlay buffer.");
  213.         
  214.     //•    Make it the active underlay
  215.     theError = DSpContext_SetUnderlayAltBuffer(gDisplayContext, gUnderlay);
  216.     if (theError)
  217.         FatalError("Could not set underlay buffer.");
  218. }
  219.  
  220. //•    --------------------    GraphicsGetUnderlayGrafPort
  221.  
  222. void
  223. GraphicsGetUnderlayGrafPort(CGrafPtr *underlay, GDHandle *device)
  224. {
  225.     DSpAltBuffer_GetCGrafPtr(gUnderlay, kDSpBufferKind_Normal, underlay, device);
  226. }
  227.  
  228. #pragma mark —————  Image Management  —————
  229.  
  230. //•    --------------------    GraphicsLoadBackground
  231.  
  232. void
  233. GraphicsLoadBackground(SInt16 whichBG)
  234. {
  235. GrafPtr        oldPort;
  236. GDHandle    oldDevice;
  237. GDHandle    underlayDevice;
  238. PicHandle    thePict;
  239. CGrafPtr    backBuff;
  240. Rect        r;
  241.  
  242.     thePict = GetPicture(whichBG);
  243.     if (! thePict)
  244.         FatalError("Could not load background.");
  245.  
  246.     //•    Get a CGrafPtr reference to the underlay graphics buffer
  247.     DSpAltBuffer_GetCGrafPtr(gUnderlay, kDSpBufferKind_Normal, &backBuff, &underlayDevice);
  248.     
  249.     GetPort(&oldPort);
  250.     oldDevice = GetGDevice();
  251.     
  252.     SetPort((GrafPtr) backBuff);
  253.     SetGDevice(underlayDevice);
  254.  
  255.     RGBForeColor(&rgbBlack);
  256.     RGBBackColor(&rgbWhite);
  257.     
  258.     //•    Fill the background with black
  259.     PaintRect(&backBuff->portRect);
  260.  
  261.     HLock((Handle) thePict);
  262.  
  263.     SetRect(&r, 0, 0, 640, 440);
  264.     DrawPicture(thePict, &r);
  265.     KillPictureZ(&thePict);
  266.  
  267.     //•    Invalidate the entire underlay so that all other back buffers
  268.     //•    get the new image copied up to them.
  269.     DSpAltBuffer_InvalRect(gUnderlay, &backBuff->portRect);
  270.  
  271.     SetPort(oldPort);
  272.     SetGDevice(oldDevice);
  273. }
  274.  
  275. //•    --------------------    GraphicsMergeCLUT
  276.  
  277. void
  278. GraphicsMergeCLUT(SInt16 clutID, UInt16 firstColor, UInt16 lastColor)
  279. {
  280. CTabHandle    ct;
  281. UInt32        i;
  282.  
  283.      //•    Load the appropritate 'CLUT' resource
  284.      ct = GetCTable(clutID);
  285.     if (! ct)
  286.         FatalError("Could not load color table for merge.");
  287.         
  288.     HLock((Handle) ct);
  289.     
  290.     //•    Copy colors from it to our game color table
  291.     for (i = firstColor; i <= lastColor; i++)
  292.     {
  293.         (**gGameCLUT).ctTable[i].rgb.red = (**ct).ctTable[i].rgb.red;
  294.         (**gGameCLUT).ctTable[i].rgb.green = (**ct).ctTable[i].rgb.green;
  295.         (**gGameCLUT).ctTable[i].rgb.blue = (**ct).ctTable[i].rgb.blue;
  296.     }
  297.     
  298.     HUnlock((Handle) ct);
  299.     ReleaseResource((Handle) ct);
  300.  
  301.     //•    Make the new game color table the active color environment
  302.     GraphicsUpdateScreenPalette(firstColor, lastColor);
  303. }
  304.  
  305. //•    --------------------    GraphicsUpdateScreenPalette
  306.  
  307. static void
  308. GraphicsUpdateScreenPalette(UInt16 inFirstColor, UInt16 inLastColor)
  309. {
  310. OSStatus    theError;
  311.     
  312.     //•    Copy our game color table to our DrawSprocket context.  This also
  313.     //•    updates the color environment of any buffers that we've allocated with
  314.     //•    DrawSprocket.
  315.     theError = DSpContext_SetCLUTEntries(gDisplayContext, (**gGameCLUT).ctTable, inFirstColor, inLastColor - inFirstColor);
  316.     if( theError )
  317.         DebugStr("\p error from CLUT ");
  318. }
  319.  
  320. //•    --------------------    GraphicsSetRectDirty
  321.  
  322. void
  323. GraphicsSetRectDirty(RectPtr r)
  324. {
  325.     DSpContext_InvalBackBufferRect(gDisplayContext, r);
  326. }
  327.  
  328. //•    --------------------    GraphicsSetUnderlayRectDirty
  329.  
  330. void
  331. GraphicsSetUnderlayRectDirty(RectPtr r)
  332. {
  333.     DSpAltBuffer_InvalRect(gUnderlay, r);
  334. }
  335.  
  336. //•    --------------------    GraphicsUpdateScreen
  337.  
  338. void
  339. GraphicsUpdateScreen(void)
  340. {
  341.     DSpContext_SwapBuffers(gDisplayContext, nil, nil);
  342. }
  343.  
  344. #pragma mark —————  Context State  —————
  345.  
  346. //•    --------------------    GraphicsActive
  347.  
  348. void
  349. GraphicsActive(void)
  350. {
  351. OSStatus    theErr;
  352.  
  353.     HideCursor();
  354.  
  355.     theErr = DSpContext_SetState(gDisplayContext, kDSpContextState_Active);
  356.     if (theErr)
  357.         DebugStr("\pSetState active failed in GraphicsActive().");
  358. }
  359.  
  360. //•    --------------------    GraphicsPaused
  361.  
  362. void
  363. GraphicsPaused(void)
  364. {
  365.     DSpContext_SetState(gDisplayContext, kDSpContextState_Paused);
  366.     ShowCursor();
  367.     DrawMenuBar();
  368. }
  369.  
  370. //•    --------------------    GraphicsInactive
  371.  
  372. void
  373. GraphicsInactive(void)
  374. {
  375.     DSpContext_SetState(gDisplayContext, kDSpContextState_Inactive);
  376.     ShowCursor();
  377. }
  378.  
  379. //•    --------------------    GraphicsDoUpdateEvent
  380.  
  381. void
  382. GraphicsDoUpdateEvent(void)
  383. {
  384. GrafPtr        savePort;
  385. GDHandle    saveGDH;
  386.  
  387. CGrafPtr    backBuffer;
  388. CGrafPtr    frontBuffer;
  389.  
  390.     DSpContext_GetFrontBuffer(gDisplayContext, &frontBuffer);
  391.     DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &backBuffer);
  392.  
  393.     GetPort(&savePort);
  394.     saveGDH = GetGDevice();
  395.     
  396.     SetPort((GrafPtr) frontBuffer);
  397.     SetGDevice(gGameGDH);
  398.  
  399.     ForeColor(blackColor);
  400.     BackColor(whiteColor);
  401.  
  402.     CopyBits((BitMapPtr) *backBuffer->portPixMap, (BitMapPtr) *frontBuffer->portPixMap,
  403.         &backBuffer->portRect, &frontBuffer->portRect, srcCopy, nil);
  404.  
  405.     SetPort(savePort);
  406.     SetGDevice(saveGDH);
  407. }
  408.